﻿#include "MirDropDownBox.h"
#include "../Settings.h"
#include "../MirGraphics/MLibrary.h"
#include "../Forms/Client.CMain.h"

using namespace Client::MirGraphics;

namespace Client::MirControls
{

    int MirDropDownBox::getSelectedIndex() const
    {
        return _SelectedIndex;
    }

    void MirDropDownBox::setSelectedIndex(int value)
    {
        _SelectedIndex = value;
        if (_SelectedIndex >= getItems().size())
        {
            _SelectedIndex = -1;
        }
    }

    std::vector<std::string> MirDropDownBox::getItems() const
    {
        return _Items;
    }

    void MirDropDownBox::setItems(const std::vector<std::string> &value)
    {
        _Items = value;
        ItemsChanged();
    }

    void MirDropDownBox::OnBackColourChanged()
    {
        MirControl::OnBackColourChanged();
        if (_label != nullptr && !_label->isDisposed())
        {
            _label->setBackColour(getBackColour());
        }
    }

    void MirDropDownBox::OnSizeChanged()
    {
        MirControl::OnSizeChanged();
        OrigHeight = OrigHeight == 0 ? getSize()->Height : OrigHeight;
        for (int i = 0; i < _Option.size(); i++)
        {
            Size tempVar(getSize()->Width - 16, 16);
            _Option[i]->setSize(&tempVar); //Size.Width - 13, 13
        }

        if (_label != nullptr && !_label->isDisposed())
        {
            Size tempVar2(getSize()->Width - 16, 15);
            _label->setSize(&tempVar2); //Size.Width - 16, 12
        }
        if (_DropDownButton != nullptr && !_DropDownButton->isDisposed())
        {
            Point tempVar3(getSize()->Width - 18, 2);
            _DropDownButton->setLocation(&tempVar3);
        }
        if (_ScrollUp != nullptr && !_ScrollUp->isDisposed())
        {
            Point tempVar4(getSize()->Width - 12, 14);
            _ScrollUp->setLocation(&tempVar4);
        }
        if (_ScrollDown != nullptr && !_ScrollDown->isDisposed())
        {
            Point tempVar5(getSize()->Width - 12, 52);
            _ScrollDown->setLocation(&tempVar5);
        }
        if (_ScrollPosition != nullptr && !_ScrollPosition->isDisposed())
        {
            Point tempVar6(getSize()->Width - 11, 22);
            _ScrollPosition->setLocation(&tempVar6);
        }

    }

    void MirDropDownBox::OnEnabledChanged()
    {
        MirControl::OnEnabledChanged();
        if (_DropDownButton != nullptr && !_DropDownButton->isDisposed())
        {
            _DropDownButton->setEnabled(getEnabled());
            if (getEnabled())
            {
                _DropDownButton->setVisible(true);
            }
            else
            {
                _DropDownButton->setVisible(false);
            }
        }
    }

    MirDropDownBox::MirDropDownBox()
    {
        setBackColour(Color::FromArgb(255,6,6,6));
        setForeColour(Color::White);
        setEnabled(false);
        _label = new MirLabel();
        _label->setParent(this);
        Point tempVar(0, 0);
        _label->setLocation(&tempVar);
        _label->setForeColour(getForeColour());
        _label->setBackColour(getBackColour());
        Font tempVar2(Settings::FontName, 8.0F);
        _label->setFont(&tempVar2);
        _label->setVisible(true);
        _label->Click += [&] (o, e)
        {
            if (_DropDownButton->getEnabled())
            {
                DropDownClick();
            }
        };
        _label->BeforeDraw += [&] (o, e)
        {
            if ((getItems().size() > 0) && (getItems().size() >= getSelectedIndex()))
            {
                if (getSelectedIndex() == -1)
                {
                    _label->setText(" ");
                }
                else
                {
    
                    _label->setText(getItems()[getSelectedIndex()]);
                }
            }
            else
            {
                _label->setText("None");
            }
        };
        for (int i = 0; i < _Option.size(); i++)
        {
            MirLabel *tempVar3 = new MirLabel();
            tempVar3->setParent(this);
            tempVar3->setVisible(false);
            Point tempVar4(0, 15 + (i * 13));
            tempVar3->setLocation(&tempVar4);
            tempVar3->setForeColour(getForeColour());
            tempVar3->setBackColour(Color::FromArgb(255,20,20,20));
            Font tempVar5(Settings::FontName, 8.0F);
            tempVar3->setFont(&tempVar5);
            _Option[i] = tempVar3;
            int index = i;
            _Option[index]->MouseEnter += [&] (o, e)
            {
                _Option[index]->setBackColour(Color::FromArgb(255,140,70,0));
            };
            _Option[index]->MouseLeave += [&] (o, e)
            {
                _Option[index]->setBackColour(Color::FromArgb(255, 20, 20, 20));
            };
            _Option[index]->MouseDown += [&] (o, e)
            {
                _Option[index]->setBackColour(Color::FromArgb(255, 20, 20, 20));
            };
            _Option[index]->MouseUp->addListener([&] (o, e)
            {
                _Option[index]->setBackColour(Color::FromArgb(255,20,20,20));
            });
            _Option[index]->Click += [&] (o, e)
            {
                SelectOption(index);
            };

            _Option[index]->BeforeDraw += [&] (o, e)
            {
                if (getItems().size() > (ScrollIndex + index + MinimumOption))
                {
                    _Option[index]->setText(_Items[ScrollIndex + index + MinimumOption]);
                }
            };

            delete tempVar3;
        }
        _DropDownButton = new MirButton();
        _DropDownButton->setIndex(207);
        _DropDownButton->setLibrary(Libraries::Prguse2);
        Point tempVar6(getSize()->Width - 18, 1);
        _DropDownButton->setLocation(&tempVar6);
        _DropDownButton->setParent(this);
        _DropDownButton->setHoverIndex(208);
        _DropDownButton->setPressedIndex(209);
        _DropDownButton->setVisible(false);
        _DropDownButton->Click += [&] (o, e)
        {
            DropDownClick();
        };
        _ScrollUp = new MirButton();
        _ScrollUp->setHoverIndex(2022);
        _ScrollUp->setIndex(2021);
        _ScrollUp->setLibrary(Libraries::Prguse);
        Point tempVar7(getSize()->Width - 12, 14);
        _ScrollUp->setLocation(&tempVar7);
        _ScrollUp->setParent(this);
        _ScrollUp->setPressedIndex(2023);
        _ScrollUp->setVisible(false);
        _ScrollUp->Click += [&] (o, e)
        {
            ScrollUp();
        };
        _ScrollDown = new MirButton();
        _ScrollDown->setHoverIndex(2025);
        _ScrollDown->setIndex(2024);
        _ScrollDown->setLibrary(Libraries::Prguse);
        Point tempVar8(getSize()->Width - 12, 52);
        _ScrollDown->setLocation(&tempVar8);
        _ScrollDown->setParent(this);
        _ScrollDown->setPressedIndex(2026);
        _ScrollDown->setVisible(false);
        _ScrollDown->Click += [&] (o, e)
        {
            ScrollDown();
        };

        _ScrollPosition = new MirButton();
        _ScrollPosition->setHoverIndex(2016);
        _ScrollPosition->setIndex(2015);
        _ScrollPosition->setLibrary(Libraries::Prguse);
        Point tempVar9(getSize()->Width - 11, 22);
        _ScrollPosition->setLocation(&tempVar9);
        _ScrollPosition->setMovable(true);
        _ScrollPosition->setParent(this);
        _ScrollPosition->setPressedIndex(2017);
        _ScrollPosition->setVisible(false);
        _ScrollPosition->OnMoving->addListener("ScrollPosition", std::bind(&MirDropDownBox::ScrollPosition, this, std::placeholders::_1, std::placeholders::_2));
        BeforeDraw += MirDropDownBox_BeforeDraw;
    }

    void MirDropDownBox::MirDropDownBox_BeforeDraw(std::any sender, EventArgs *e)
    {
        if (!_Option[0]->getVisible())
        {
            return;
        }
        if (IsMouseOver(CMain::MPoint))
        {
            return;
        }
        for (auto control : getControls())
        {
            if (control->IsMouseOver(CMain::MPoint))
            {
                return;
            }
        }

        CloseDropDown();
    }

    void MirDropDownBox::OnMouseLeave()
    {
        if (!IsMouseOver(CMain::MPoint))
        {
            CloseDropDown();
        }
        MirControl::OnMouseLeave();
    }

    void MirDropDownBox::SelectOption(int index)
    {
        if (ScrollIndex + index + MinimumOption < getItems().size())
        {
            _WantedIndex = ScrollIndex + index + MinimumOption;
            if (ValueChanged != nullptr)
            {
                ValueChanged::Invoke(this, EventArgs::Empty);
            }
        }
        else
        {
            Update();
        }
        CloseDropDown();
    }

    void MirDropDownBox::ItemsChanged()
    {
        CloseDropDown();
        setSelectedIndex(-1);
    }

    void MirDropDownBox::Update()
    {
        // Member is not implemented.
    }

    void MirDropDownBox::DropDownClick()
    {
        if (_Option[0]->getVisible())
        {
            CloseDropDown();
        }
        else
        {
            OpenDropDown();
        }
    }

    void MirDropDownBox::OpenDropDown()
    {
        Size tempVar(getSize()->Width, OrigHeight + (std::max(5, getItems().size()) * 15));
        setSize(&tempVar);
        ScrollIndex = 0;
        if (getItems().size() > 5)
        {
            ScrollIndex = getSelectedIndex() > 3 ? getSelectedIndex() - 2 : 0;
        }
        for (int i = 0; i < _Option.size(); i++)
        {
            if (getItems().size() > i)
            {
                _Option[i]->setVisible(true);
            }
            else
            {
                _Option[i]->setVisible(false);
            }
        }
        if (getItems().size() > 5)
        {
            _ScrollDown->setVisible(true);
            _ScrollPosition->setVisible(true);
            _ScrollUp->setVisible(true);
        }
        else
        {
            _ScrollDown->setVisible(false);
            _ScrollPosition->setVisible(false);
            _ScrollUp->setVisible(false);
        }
        Point tempVar2(getSize()->Width - 12, 9 + std::min(5, getItems().size()) * 13);
        _ScrollDown->setLocation(&tempVar2);
    }

    void MirDropDownBox::CloseDropDown()
    {
        Size tempVar(getSize()->Width, OrigHeight);
        setSize(&tempVar);
        for (int i = 0; i < _Option.size(); i++)
        {
            _Option[i]->setVisible(false);
        }
        _ScrollDown->setVisible(false);
        _ScrollPosition->setVisible(false);
        _ScrollUp->setVisible(false);
    }

    void MirDropDownBox::ScrollUp()
    {
        if (ScrollIndex > 0)
        {
            ScrollIndex--;
        }
        Update();
    }

    void MirDropDownBox::ScrollDown()
    {
        if (ScrollIndex < (getItems().size() - 5))
        {
            ScrollIndex++;
        }
        Update();
    }

    void MirDropDownBox::ScrollPosition(std::any sender, MouseEventArgs *e)
    {
        int x = getSize()->Width - 11;
        int y = _ScrollPosition->getLocation()->Y;
        if (y >= _ScrollDown->getLocation()->Y - 14)
        {
            y = _ScrollDown->getLocation()->Y - 14;
        }
        if (y < 20)
        {
            y = 20;
        }

        int h = _ScrollDown->getLocation()->Y - _ScrollUp->getLocation()->Y + 6;
        h = static_cast<int>((y - 15) / (h / static_cast<float>(getItems().size() - 1)));
        if (h > getItems().size() - 5)
        {
            h = std::max(0, getItems().size() - 5);
        }
        if (h != ScrollIndex)
        {
            ScrollIndex = h;
            Update();
        }

        Point tempVar(x, y);
        _ScrollPosition->setLocation(&tempVar);
    }

    void MirDropDownBox::Dispose(bool disposing)
    {
        MirControl::Dispose(disposing);

        if (!disposing)
        {
            return;
        }

        if (_label != nullptr && !_label->isDisposed())
        {
            _label->Dispose();
        }
        _label = nullptr;

        if (_DropDownButton != nullptr && !_DropDownButton->isDisposed())
        {
            _DropDownButton->Dispose();
        }
        _DropDownButton = nullptr;

        if (_ScrollDown != nullptr && !_ScrollDown->isDisposed())
        {
            _ScrollDown->Dispose();
        }
        _ScrollDown = nullptr;

        if (_ScrollPosition != nullptr && !_ScrollPosition->isDisposed())
        {
            _ScrollPosition->Dispose();
        }
        _ScrollPosition = nullptr;

        if (_ScrollUp != nullptr && !_ScrollUp->isDisposed())
        {
            _ScrollUp->Dispose();
        }
        _ScrollUp = nullptr;
        for (int i = 0; i < _Option.size(); i++)
        {
            if (_Option[i] != nullptr && !_Option[i]->isDisposed())
            {
                _Option[i]->Dispose();
            }
            _Option[i] = nullptr;
        }
    }
}
